home *** CD-ROM | disk | FTP | other *** search
/ Pascal Super Library / Pascal Super Library (CW International)(1997).bin / LIBRARY / WAFPEGTP / NOVELL.PAS < prev    next >
Pascal/Delphi Source File  |  1994-01-16  |  60KB  |  2,062 lines

  1. UNIT Novell;
  2.  
  3. {
  4.   + apiavailable boolean and currentversion string now set at unit
  5.     initialization. If not apiavailable then halt will prevent any
  6.     programs which need netware from running rml 14/August 1992.
  7.  
  8. {---------------------------------------------------------------------------}
  9. {                                                                           }
  10. {  This UNIT provides a method of obtaining Novell information from a user  }
  11. {  written program.  This UNIT was tested on an IBM AT running DOS 4.0 &    }
  12. {  using Netware 2.15.  The unit compiled cleanly under Turbo Pascal 6.0    }
  13. {                                                                           }
  14. {  The UNIT has been updated to compile and run under Turbo Pascal for      }
  15. {  Windows.                                                                 }
  16. {                                                                           }
  17. {  Last Update:   28 May 91                                                 }
  18. {---------------------------------------------------------------------------}
  19. {                                                                           }
  20. {  Any questions can be directed to:                                        }
  21. {                                                                           }
  22. {  Mark Bramwell                                                            }
  23. {  University of Western Ontario                                            }
  24. {  London, Ontario, N6A 3K7                                                 }
  25. {                                                                           }
  26. {  Phone:  519-473-3618 [work]              519-473-3618 [home]             }
  27. {                                                                           }
  28. {  Bitnet: mark@hamster.business.uwo.ca     Packet: ve3pzr @ ve3gyq         }
  29. {                                                                           }
  30. {  Anonymous FTP Server Internet Address: 129.100.22.100                    }
  31. {                                                                           }
  32. {---------------------------------------------------------------------------}
  33.  
  34. { Any other Novell UNITS gladly accepted. }
  35.  
  36.  
  37. {
  38. mods July 19 1991, rml added translate_netaddress
  39. mods February 1 1991, Ross Lazarus (rml@extro.ucc.su.AU.OZ)
  40.      var retcodes in procedure getservername, get_broadcast_message,
  41.      verify_object_password comments, password conversion to upper case,
  42.  
  43. Seems to work fine on a Netware 3.00 and on 3.01 servers -
  44. }
  45.  
  46.  
  47. INTERFACE
  48.  
  49. {$IFDEF WINDOWS}
  50. Uses WinDos;
  51. {$ENDIF WINDOWS}
  52.  
  53. {$IFNDEF WINDOWS}
  54. Uses Dos;
  55. {$ENDIF WINDOWS}
  56.  
  57. Const
  58.   apiavailable : boolean = false;
  59.   currentversion : string[30] = '';
  60.   Months : Array [1..12] of String[3] = ('JAN','FEB','MAR','APR','MAY','JUN',
  61.                                          'JUL','AUG','SEP','OCT','NOV','DEC');
  62.  
  63.   HEXDIGITS : Array [0..15] of char = '0123456789ABCDEF';
  64.  
  65. VAR
  66.  
  67. {----------------------------------------------------------------------}
  68. {  The following values can be pulled from an user written application }
  69. {                                                                      }
  70. {  The programmer would first call   GetServerInfo.                    }
  71. {  Then he could   writeln(serverinfo.name)   to print the server name }
  72. {----------------------------------------------------------------------}
  73.       ServerInfo    : Record
  74.                      ReturnLength    : Integer;
  75.                      Server          : Packed Array [1..48] of Byte;
  76.                      NetwareVers     : Byte;
  77.                      NetwareSubV     : Byte;
  78.                      ConnectionMax   : array [1..2] of byte;
  79.                      ConnectionUse   : array [1..2] of byte;
  80.                      MaxConVol       : array [1..2] of byte; {}
  81.                      OS_revision     : byte;
  82.                      SFT_level       : byte;
  83.                      TTS_level       : byte;
  84.                      peak_used       : array [1..2] of byte;
  85.                   accounting_version : byte;
  86.                      vap_version     : byte;
  87.                      queuing_version : byte;
  88.                 print_server_version : byte;
  89.              virtual_console_version : byte;
  90.        security_restrictions_version : byte;
  91.         Internetwork_version_version : byte;
  92.                         Undefined    : Packed Array [1..60] of Byte;
  93.                peak_connections_used : integer;
  94.                      Connections_max : integer;
  95.                   Connections_in_use : integer;
  96.                Max_connected_volumes : integer;
  97.                                 name : string;
  98.                    End;
  99.  
  100. function first_networked_drive : char;
  101. { find first drive letter which is a networked (non local) one }
  102.  
  103. function getnamefromhexid(hexid : string) : string;
  104.  
  105. procedure GetConnectionInfo(var LogicalStationNo: integer;
  106.                             var name,hex_id:string;
  107.                             var conntype:integer;
  108.                             var datetime:string;
  109.                             var retcode:integer);
  110. { returns username and login date/time when you supply the station number. }
  111.  
  112. procedure clear_connection(connection_number : integer; var retcode : integer);
  113. { kicks the workstation off the server}
  114.  
  115. procedure GetHexID(var userid,hexid: string;
  116.                    var retcode: integer);
  117. { returns the novell hexid of an username when you supply the username. }
  118.  
  119. procedure GetServerInfo;
  120. { returns various info of the default server }
  121.  
  122. procedure GetUser( var _station: integer;
  123.                    var _username: string;
  124.                    var retcode:integer);
  125. { returns logged-in station username when you supply the station number. }
  126.  
  127. procedure GetNode( var hex_addr: string;
  128.                    var retcode: integer);
  129. { returns your physical network node in hex. }
  130.  
  131. procedure GetStation( var _station: integer;
  132.                       var retcode: integer);
  133. { returns the station number of your workstation }
  134.  
  135. procedure GetServerName(var servername : string;
  136.                         var retcode : integer);
  137.  
  138. { returns the name of the current server }
  139.  
  140. procedure Send_Message_to_Username(username,message : string;
  141.                                    var retcode: integer);
  142. { Sends a novell message to the userid's workstation }
  143.  
  144. procedure Send_Message_to_Station(station:integer;
  145.                                   message : string;
  146.                                   var retcode: integer);
  147. { Sends a message to the workstation station # }
  148.  
  149. procedure Get_Volume_Name(var volume_name: string;
  150.                           volume_number: integer;
  151.                           var retcode:integer);
  152. { Gets the Volume name from Novell network drive }
  153. { Example:  SYS    Note: default drive must be a }
  154. { network drive.                                 }
  155.  
  156. procedure get_realname(var userid:string;
  157.                        var realname:string;
  158.                        var retcode:integer);
  159. { You supply the userid, and it returns the realname as stored by syscon. }
  160. { Example:  userid=mbramwel   realname=Mark Bramwell }
  161.  
  162. procedure get_broadcast_mode(var bmode:integer);
  163.  
  164. procedure set_broadcast_mode(bmode:integer);
  165.  
  166. procedure get_broadcast_message(var bmessage: string;
  167.                                 var retcode : integer);
  168.  
  169. procedure get_server_datetime(var _year,_month,_day,_hour,_min,_sec,_dow:integer);
  170. { pulls from the server the date, time and Day Of Week }
  171.  
  172. procedure set_date_from_server;
  173. { pulls the date from the server and updates the workstation's clock }
  174.  
  175. procedure set_time_from_server;
  176. { pulls the time from the server and updates the workstation's clock }
  177.  
  178. procedure get_server_version(var _version : string);
  179.  
  180. procedure open_message_pipe(var _connection, retcode : integer);
  181.  
  182. procedure close_message_pipe(var _connection, retcode : integer);
  183.  
  184. procedure check_message_pipe(var _connection, retcode : integer);
  185.  
  186. procedure send_personal_message(var _connection : integer; var _message : string; var retcode : integer);
  187.  
  188. procedure get_personal_message(var _connection : integer; var _message : string; var retcode : integer);
  189.  
  190. procedure get_drive_connection_id(var drive_number,
  191.                                   server_number : integer);
  192. {pass the drive number - it returns the server number if a network volume}
  193.  
  194. procedure get_file_server_name(var server_number : integer;
  195.                                var server_name : string);
  196.  
  197. procedure get_directory_path(var handle : integer;
  198.                              var pathname : string;
  199.                              var retcode : integer);
  200.  
  201. procedure get_drive_handle_id(var drive_number, handle_number : integer);
  202.  
  203. procedure set_preferred_connection_id(server_num : integer);
  204.  
  205. procedure get_preferred_connection_id(var server_num : integer);
  206.  
  207. procedure set_primary_connection_id(server_num : integer);
  208.  
  209. procedure get_primary_connection_id(var server_num : integer);
  210.  
  211. procedure get_default_connection_id(var server_num : integer);
  212.  
  213. procedure Get_Internet_Address(station : integer;
  214.                                var net_number, node_addr, socket_number : string;
  215.                                var retcode : integer);
  216.  
  217. procedure login_to_file_server(obj_type:integer; _name,_password : string;var retcode:integer);
  218.  
  219. procedure logout;
  220.  
  221. procedure logout_from_file_server(var id: integer);
  222.  
  223. procedure down_file_server(flag:integer;var retcode : integer);
  224.  
  225. procedure detach_from_file_server(var id,retcode:integer);
  226.  
  227. procedure disable_file_server_login(var retcode : integer);
  228.  
  229. procedure enable_file_server_login(var retcode : integer);
  230.  
  231. procedure alloc_permanent_directory_handle(var _dir_handle : integer;
  232.                                            var _drive_letter : string;
  233.                                            var _dir_path_name : string;
  234.                                            var _new_dir_handle : integer;
  235.                                            var _effective_rights: byte;
  236.                                            var _retcode : integer);
  237.  
  238. procedure map(var drive_spec:string;
  239.               var _rights:byte;
  240.               var _retcode : integer);
  241.  
  242. procedure scan_object(var last_object: longint;
  243.                       var search_object_type: integer;
  244.                       var search_object : string;
  245.                       var replyid : longint;
  246.                       var replytype : integer; var replyname : string;
  247.                       var replyflag : integer; var replysecurity : byte;
  248.                       var replyproperties : integer; var retcode : integer);
  249.  
  250. procedure verify_object_password(var object_type:integer; var object_name,password : string; var retcode : integer);
  251.  
  252. {--------------------------------------------------------------------------}
  253. { file locking routines }
  254. {-----------------------}
  255.  
  256. procedure log_file(lock_directive:integer; log_filename: string; log_timeout:integer; var retcode:integer);
  257.  
  258. procedure clear_file_set;
  259.  
  260. procedure lock_file_set(lock_timeout:integer; var retcode:integer);
  261.  
  262. procedure release_file_set;
  263.  
  264. procedure release_file(log_filename: string; var retcode:integer);
  265.  
  266. procedure clear_file(log_filename: string; var retcode:integer);
  267.  
  268. {-----------------------------------------------------------------------------}
  269.  
  270. procedure open_semaphore( _name:string;
  271.                           _initial_value:shortint;
  272.                           var _open_count:integer;
  273.                           var _handle:longint;
  274.                           var retcode:integer);
  275.  
  276. procedure close_semaphore(var _handle:longint; var retcode:integer);
  277.  
  278. procedure examine_semaphore(var _handle:longint; var _value:shortint; var _count, retcode:integer);
  279.  
  280. procedure signal_semaphore(var _handle:longint; var retcode:integer);
  281.  
  282. procedure wait_on_semaphore(var _handle:longint; _timeout:integer; var retcode:integer);
  283.  
  284. {-----------------------------------------------------------------------------}
  285.  
  286.  
  287. IMPLEMENTATION
  288.  
  289. const
  290.      zero = '0';
  291.  
  292. var
  293.    retcode : byte; { return code for all functions }
  294.  
  295. {$IFDEF WINDOWS}
  296.   regs : TRegisters;   { Turbo Pascal for Windows }
  297. {$ENDIF WINDOWS}
  298.  
  299. {$IFNDEF WINDOWS}
  300.   regs : registers;    { Turbo Pascal for Dos }
  301. {$ENDIF WINDOWS}
  302.  
  303.  
  304.  
  305. procedure get_volume_name(var volume_name: string; volume_number: integer;
  306.                           var retcode:integer);
  307. {
  308. pulls volume names from default server.  Use set_preferred_connection_id to
  309. set the default server.
  310. retcodes:  0=ok, 1=no volume assigned  98h= # out of range
  311. }
  312.  
  313. VAR
  314.    count,count1  : integer;
  315.  
  316.    requestbuffer : record
  317.       len        : integer;
  318.       func       : byte;
  319.       vol_num    : byte;
  320.       end;
  321.  
  322.     replybuffer  : record
  323.       len        : integer;
  324.       vol_length : byte;
  325.       name       : packed array [1..16] of byte;
  326.       end;
  327.  
  328. begin
  329. With Regs do
  330. begin
  331.   ah := $E2;
  332.   ds := seg(requestbuffer);
  333.   si := ofs(requestbuffer);
  334.   es := seg(replybuffer);
  335.   di := ofs(replybuffer);
  336.  end;
  337.  With requestbuffer do
  338.  begin
  339.   len  := 2;
  340.   func := 6;
  341.   vol_num := volume_number;  {passed from calling program}
  342.  end;
  343.  With replybuffer do
  344.  begin
  345.   len :=  17;
  346.   vol_length := 0;
  347.   for count := 1 to 16 do name[count] := $00;
  348.  end;
  349.  msdos(Regs);
  350.  volume_name := '';
  351.  if replybuffer.vol_length > 0 then
  352.     for count := 1 to replybuffer.vol_length do
  353.         volume_name := volume_name + chr(replybuffer.name[count]);
  354.  retcode := Regs.al;
  355. end;
  356.  
  357. procedure verify_object_password(var object_type:integer; var object_name,password : string; var retcode : integer);
  358. {
  359. for netware 3.xx remember to have previously (eg in the autoexec file )
  360. set allow unencrypted passwords = on
  361. on the console, otherwise this call always fails !
  362. Note that intruder lockout status is affected by this call !
  363. Netware security isn't that stupid....
  364. Passwords appear to need to be converted to upper case
  365.  
  366. retcode      apparent meaning as far as I can work out....
  367.  
  368. 0            verification of object_name/password combination
  369. 197          account disabled due to intrusion lockout
  370. 214          unencrypted password calls not allowed on this v3+ server
  371. 252          no such object_name on this server
  372. 255          failure to verify object_name/password combination
  373.  
  374. }
  375. var  request_buffer : record
  376.       buffer_length : integer;
  377.         subfunction : byte;
  378.            obj_type : array [1..2] of byte;
  379.     obj_name_length : byte;
  380.            obj_name : array [1..47] of byte;
  381.     password_length : byte;
  382.        obj_password : array [1..127] of byte;
  383.                 end;
  384.  
  385.        reply_buffer : record
  386.       buffer_length : integer;
  387.                 end;
  388.  
  389.               count : integer;
  390.  
  391. begin
  392.      With request_buffer do
  393.      begin
  394.           buffer_length := 179;
  395.           subfunction := $3F;
  396.           obj_type[1] := 0;
  397.           obj_type[2] := object_type;
  398.           obj_name_length := 47;
  399.           for count := 1 to 47 do
  400.               obj_name[count] := $00;
  401.           for count := 1 to length(object_name) do
  402.           obj_name[count] := ord(object_name[count]);
  403.           password_length := length(password);
  404.           for count := 1 to 127 do
  405.               obj_password[count] := $00;
  406.           if password_length > 0 then
  407.              for count := 1 to password_length do
  408.                  obj_password[count] := ord(upcase(password[count]));
  409.        end;
  410.        With reply_buffer do
  411.             buffer_length := 0;
  412.        With regs do
  413.        begin
  414.             Ah := $E3;
  415.             Ds := Seg(Request_Buffer);
  416.             Si := Ofs(Request_Buffer);
  417.             Es := Seg(Reply_Buffer);
  418.             Di := Ofs(Reply_Buffer);
  419.        End;
  420.        msdos(regs);
  421.        retcode := regs.al;
  422. end; { verify_object_password }
  423.  
  424.  
  425.  
  426. procedure scan_object(var last_object: longint; var search_object_type: integer;
  427.                       var search_object : string; var replyid : longint;
  428.                       var replytype : integer; var replyname : string;
  429.                       var replyflag : integer; var replysecurity : byte;
  430.                       var replyproperties : integer; var retcode : integer);
  431. var
  432.     request_buffer : record
  433.      buffer_length : integer;
  434.        subfunction : byte;
  435.          last_seen : longint;
  436.        search_type : word {array [1..2] of byte};
  437.        name_length : byte;
  438.        search_name : array [1..47] of byte;
  439.                end;
  440.  
  441.       reply_buffer : record
  442.      buffer_length : integer;
  443.          object_id : longint;
  444.        object_type : array [1..2] of byte;
  445.        object_name : array [1..48] of byte;
  446.        object_flag : byte;
  447.           security : byte;
  448.         properties : byte;
  449.                end;
  450.  
  451.              count : integer;
  452.  
  453. begin
  454. with request_buffer do
  455. begin
  456.  buffer_length := 55;
  457.  subfunction := $37;
  458.  last_seen := last_object;
  459.  if search_object_type = -1 then { -1 = wildcard }
  460.    begin
  461.         search_type := $ffff;
  462.    {
  463.    search_type[1] := $ff;
  464.    search_type[2] := $ff;
  465.    }
  466.    end else
  467.    begin
  468.         search_type := search_object_type;
  469.         search_type := search_type shl 8;
  470.         {
  471.    search_type[1] := 0;
  472.    search_type[2] := search_object_type;
  473.         }
  474.    end;
  475. name_length := length(search_object);
  476. for count := 1 to 47 do search_name[count] := $00;
  477. if name_length > 0 then for count := 1 to name_length do
  478.    search_name[count] := ord(upcase(search_object[count]));
  479. end;
  480. With reply_buffer do
  481. begin
  482.  buffer_length := 57;
  483.  object_id:= 0;
  484.  object_type[1] := 0;
  485.  object_type[2] := 0;
  486.  for count := 1 to 48 do object_name[count] := $00;
  487.  object_flag := 0;
  488.  security := 0;
  489.  properties := 0;
  490. end;
  491. With Regs Do Begin
  492.  Ah := $E3;
  493.  Ds := Seg(Request_Buffer);
  494.  Si := Ofs(Request_Buffer);
  495.  Es := Seg(Reply_Buffer);
  496.  Di := Ofs(Reply_Buffer);
  497. End;
  498. msdos(regs);
  499. retcode := regs.al;
  500. With reply_buffer do
  501. begin
  502.  replyflag := object_flag;
  503.  replyproperties := properties;
  504.  replysecurity := security;
  505.  replytype := object_type[2];
  506.  replyid := object_id;
  507. end;
  508. count := 1;
  509. replyname := '';
  510. While (count <= 48)  and (reply_buffer.Object_Name[count] <> 0) Do Begin
  511.     replyName := replyname + Chr(reply_buffer.Object_name[count]);
  512.     count := count + 1;
  513.     End { while };
  514. end;
  515.  
  516.  
  517. procedure alloc_permanent_directory_handle
  518.   (var _dir_handle : integer; var _drive_letter : string;
  519.    var _dir_path_name : string; var _new_dir_handle : integer;
  520.    var _effective_rights: byte; var _retcode : integer);
  521.  
  522. var request_buffer : record
  523.      buffer_length : integer;
  524.        subfunction : byte;
  525.         dir_handle : byte;
  526.       drive_letter : byte;
  527.    dir_path_length : byte;
  528.      dir_path_name : packed array [1..255] of byte;
  529.                end;
  530.  
  531.       reply_buffer : record
  532.      buffer_length : integer;
  533.     new_dir_handle : byte;
  534.   effective_rights : byte;
  535.                end;
  536.  
  537.   count : integer;
  538.  
  539. begin
  540. With request_buffer do
  541. begin
  542.  buffer_length := 259;
  543.  subfunction := $12;
  544.  dir_handle := _dir_handle;
  545.  drive_letter := ord(upcase(_drive_letter[1]));
  546.  dir_path_length := length(_dir_path_name);
  547.  {
  548.  for count := 1 to 255 do dir_path_name[count] := $0;
  549.  }
  550.  fillchar(dir_path_name,255,$0);
  551.  if dir_path_length > 0 then for count := 1 to dir_path_length do
  552.     dir_path_name[count] := ord(upcase(_dir_path_name[count]));
  553. end;
  554. With reply_buffer do
  555. begin
  556.  buffer_length := 2;
  557.  new_dir_handle := 0;
  558.  effective_rights := 0;
  559. end;
  560. With Regs Do Begin
  561.  Ah := $E2;
  562.  Ds := Seg(Request_Buffer);
  563.  Si := Ofs(Request_Buffer);
  564.  Es := Seg(Reply_Buffer);
  565.  Di := Ofs(Reply_Buffer);
  566. End;
  567. msdos(regs);
  568. _retcode := regs.al;
  569. _effective_rights := $0;
  570. _new_dir_handle := $0;
  571. if _retcode = 0 then
  572. begin
  573.  _effective_rights := reply_buffer.effective_rights;
  574.  _new_dir_handle := reply_buffer.new_dir_handle;
  575. end;
  576. end;
  577.  
  578. function mirt(trime : String) : String;
  579. { trim all blanks }
  580.  
  581. const
  582.      blank = ' ';
  583.  
  584. var
  585.    l : integer;
  586.    t : string;
  587.  
  588. begin
  589.      t := '';
  590.      for l := 1 to length(trime) do
  591.          if (trime[l] <> blank) then
  592.             t := t + trime[l];
  593.      mirt := t;
  594. end; { mirt }
  595.  
  596. procedure map(var drive_spec:string; var _rights:byte; var _retcode : integer);
  597. var
  598.     dir_handle : integer;
  599.      path_name : string;
  600.         rights : byte;
  601.   drive_number : integer;
  602.   drive_letter : string;
  603.     new_handle : integer;
  604.        retcode : integer;
  605.  
  606. begin
  607.  {first thing is we strip leading and trailing blanks}
  608.  drive_spec := mirt(drive_spec);
  609.  path_name := '';
  610.  drive_number := ord(upcase(drive_spec[1]))-65;
  611.  drive_letter := upcase(drive_spec[1]);
  612.  if length(drive_spec) > 4 then
  613.     path_name := copy(drive_spec,4,length(drive_spec));
  614.  get_drive_handle_id(drive_number,dir_handle);
  615.  alloc_permanent_directory_handle(dir_handle,drive_letter,path_name,new_handle,rights,retcode);
  616.  _retcode := retcode;
  617.  _rights := rights;
  618. end;
  619.  
  620.  
  621.  
  622.  
  623. procedure down_file_server(flag:integer;var retcode : integer);
  624. var
  625.  
  626. request_buffer : record
  627.  buffer_length : integer;
  628.    subfunction : byte;
  629.      down_flag : byte;
  630.            end;
  631.  
  632.   reply_buffer : record
  633.  buffer_length : integer;
  634.            end;
  635.  
  636. begin
  637. With request_buffer do
  638. begin
  639.  buffer_length := 2;
  640.  subfunction := $D3;
  641.  down_flag := flag;
  642. end;
  643. reply_buffer.buffer_length := 0;
  644. With Regs Do Begin
  645.  Ah := $E3;
  646.  Ds := Seg(Request_Buffer);
  647.  Si := Ofs(Request_Buffer);
  648.  Es := Seg(Reply_Buffer);
  649.  Di := Ofs(Reply_Buffer);
  650. End;
  651. msdos(regs);
  652. retcode := regs.al;
  653. end;
  654.  
  655.  
  656. procedure set_preferred_connection_id(server_num : integer);
  657. begin
  658.  regs.ah := $F0;
  659.  regs.al := $00;
  660.  regs.ds := 0;
  661.  regs.es := 0;
  662.  regs.dl := server_num;
  663.  msdos(regs);
  664. end;
  665.  
  666. procedure set_primary_connection_id(server_num : integer);
  667. begin
  668.  regs.ah := $F0;
  669.  regs.al := $04;
  670.  regs.ds := 0;
  671.  regs.es := 0;
  672.  regs.dl := server_num;
  673.  msdos(regs);
  674. end;
  675.  
  676. procedure get_primary_connection_id(var server_num : integer);
  677. begin
  678.  regs.ah := $F0;
  679.  regs.al := $05;
  680.  regs.es := 0;
  681.  regs.ds := 0;
  682.  msdos(regs);
  683.  server_num := regs.al;
  684. end;
  685.  
  686. procedure get_default_connection_id(var server_num : integer);
  687. begin
  688.  regs.ah := $F0;
  689.  regs.al := $02;
  690.  regs.es := 0;
  691.  regs.ds := 0;
  692.  msdos(regs);
  693.  server_num := regs.al;
  694. end;
  695.  
  696. procedure get_preferred_connection_id(var server_num : integer);
  697. begin
  698.  regs.ah := $F0;
  699.  regs.al := $02;
  700.  regs.ds := 0;
  701.  regs.es := 0;
  702.  msdos(regs);
  703.  server_num := regs.al;
  704. end;
  705.  
  706.  
  707. procedure get_drive_connection_id(var drive_number, server_number : integer);
  708. {
  709. returns server number for currently mapped drives
  710. returns 0 for server number if drive number is not mapped
  711. makes it possible to find the first network drive if lastdrive
  712. has been fiddled in config.sys
  713. }
  714. var
  715.  
  716.  drive_table : array [1..32] of byte;
  717.        count : integer;
  718.            p : ^byte;
  719.  
  720. begin
  721.   regs.ah := $EF;
  722.   regs.al := $02;
  723.   regs.es := 0;
  724.   regs.ds := 0;
  725.   msdos(regs);
  726.   p := ptr(regs.es, regs.si);
  727.   move(p^,drive_table,32);
  728.   if ((drive_number < 0) or (drive_number > 32))  then drive_number := 1;
  729.   server_number := drive_table[drive_number];
  730. end;
  731.  
  732. function first_networked_drive : char;
  733. {
  734. returns the letter corresponding to the first networked drive
  735. }
  736. var
  737.    i,server : integer;
  738. begin
  739.      i := 1;
  740.      repeat
  741.           get_drive_connection_id(i,server);
  742.           if server = 0 then
  743.              inc(i);
  744.      until (server <> 0) or (i > 26);
  745.      if server = 0 then
  746.         first_networked_drive := ' '
  747.      else
  748.          first_networked_drive := chr(ord('A') + pred(i));
  749. end; { first_networked_drive }
  750.  
  751. procedure get_drive_handle_id(var drive_number, handle_number : integer);
  752. var
  753.  drive_table : array [1..32] of byte;
  754.        count : integer;
  755.            p : ^byte;
  756.  
  757. begin
  758.   regs.ah := $EF;
  759.   regs.al := $00;
  760.   regs.ds := 0;
  761.   regs.es := 0;
  762.   msdos(regs);
  763.   p := ptr(regs.es, regs.si);
  764.   move(p^,drive_table,32);
  765.   if ((drive_number < 0) or (drive_number > 32))  then drive_number := 1;
  766.   handle_number := drive_table[drive_number];
  767. end;
  768.  
  769. procedure get_directory_path(var handle : integer; var pathname : string; var retcode : integer);
  770. var count : integer;
  771.  
  772.    request_buffer : record
  773.               len : integer;
  774.       subfunction : byte;
  775.        dir_handle : byte;
  776.               end;
  777.  
  778.      reply_buffer : record
  779.               len : integer;
  780.          path_len : byte;
  781.         path_name : array [1..255] of byte;
  782.               end;
  783.  
  784. begin
  785.   With Regs Do Begin
  786.     Ah := $e2;
  787.     Ds := Seg(Request_Buffer);
  788.     Si := Ofs(Request_Buffer);
  789.     Es := Seg(Reply_Buffer);
  790.     Di := Ofs(Reply_Buffer);
  791.   End;
  792.   With request_buffer do
  793.    begin
  794.    len := 2;
  795.    subfunction := $01;
  796.    dir_handle := handle;
  797.    end;
  798.   With reply_buffer do
  799.    begin
  800.    len := 256;
  801.    path_len := 0;
  802.    for count := 1 to 255 do path_name[count] := $00;
  803.    end;
  804.   msdos(regs);
  805.   retcode := regs.al;
  806.   pathname := '';
  807.   if reply_buffer.path_len > 0 then for count := 1 to reply_buffer.path_len do
  808.      pathname := pathname + chr(reply_buffer.path_name[count]);
  809. end;
  810.  
  811.  
  812. procedure get_file_server_name(var server_number : integer; var server_name : string);
  813. var
  814.   name_table : array [1..8*48] of byte;
  815.       server : array [1..8] of string;
  816.        count : integer;
  817.       count2 : integer;
  818.            p : ^byte;
  819.      no_more : integer;
  820.  
  821. begin
  822.   regs.ah := $EF;
  823.   regs.al := $04;
  824.   regs.ds := 0;
  825.   regs.es := 0;
  826.   msdos(regs);
  827.   no_more := 0;
  828.   p := ptr(regs.es, regs.si);
  829.   move(p^,name_table,sizeof(name_table));
  830.   for count := 1 to 8 do server[count] := '';
  831.   for count := 0 to 7 do
  832.   begin
  833.     no_more := 0;
  834.     for count2 := (count*48)+1 to (count*48)+48 do if name_table[count2] <> $00
  835.         then
  836.         begin
  837.         if no_more=0 then server[count+1] := server[count+1] + chr(name_table[count2]);
  838.         end else no_more:=1; {scan until 00h is found}
  839.   end;
  840.   if ((server_number<1) or (server_number>8)) then server_number := 1;
  841.   server_name := server[server_number];
  842. end;
  843.  
  844. procedure disable_file_server_login(var retcode : integer);
  845. var  request_buffer : record
  846.       buffer_length : integer;
  847.         subfunction : byte
  848.                 end;
  849.  
  850.   reply_buffer : record
  851.  buffer_length : integer;
  852.            end;
  853.  
  854. begin
  855.   With Regs Do Begin
  856.     Ah := $E3;
  857.     Ds := Seg(Request_Buffer);
  858.     Si := Ofs(Request_Buffer);
  859.     Es := Seg(Reply_Buffer);
  860.     Di := Ofs(Reply_Buffer);
  861.   End;
  862.   With request_buffer do
  863.    begin
  864.    buffer_length := 1;
  865.    subfunction := $CB;
  866.    end;
  867.  reply_buffer.buffer_length := 0;
  868.  msdos(regs);
  869.  retcode := regs.al;
  870. end;
  871.  
  872. procedure enable_file_server_login(var retcode : integer);
  873. var request_buffer : record
  874.      buffer_length : integer;
  875.        subfunction : byte
  876.                end;
  877.  
  878.   reply_buffer : record
  879.  buffer_length : integer;
  880.            end;
  881.  
  882. begin
  883.   With Regs Do Begin
  884.     Ah := $E3;
  885.     Ds := Seg(Request_Buffer);
  886.     Si := Ofs(Request_Buffer);
  887.     Es := Seg(Reply_Buffer);
  888.     Di := Ofs(Reply_Buffer);
  889.   End;
  890.   With request_buffer do
  891.    begin
  892.    buffer_length := 1;
  893.    subfunction := $CC;
  894.    end;
  895.  reply_buffer.buffer_length := 0;
  896.  msdos(regs);
  897.  retcode := regs.al;
  898. end;
  899.  
  900.  
  901. procedure detach_from_file_server(var id,retcode:integer);
  902. begin
  903.  regs.ah := $F1;
  904.  regs.al := $01;
  905.  regs.dl := id;
  906.  msdos(regs);
  907.  retcode := regs.al;
  908. end;
  909.  
  910.  
  911. procedure getstation( var _station: integer; var retcode: integer);
  912. begin
  913.    Regs.ah := $DC;
  914.    Regs.ds := 0;
  915.    Regs.es := 0;
  916.    MsDos( Regs );
  917.    _station := Regs.al;
  918.    retcode := 0;
  919. end;
  920.  
  921.  
  922. procedure GetHexID( var userid,hexid: string; var retcode: integer);
  923. var
  924.     i,x           : integer;
  925.     hex_id        : string;
  926.     requestbuffer : record
  927.       len      : integer;
  928.       func     : byte;
  929.       conntype : packed array [1..2] of byte;
  930.       name_len : byte;
  931.       name     : packed array [1..47] of char;
  932.       end;
  933.     replybuffer   : record
  934.       len      : integer;
  935.       uniqueid1: packed array [1..2] of byte;
  936.       uniqueid2: packed array [1..2] of byte;
  937.       conntype : word;
  938.       name     : packed array [1..48] of byte;
  939.       end;
  940.  
  941. begin
  942.   regs.ah := $E3;
  943.   requestbuffer.func := $35;
  944.   regs.ds := seg(requestbuffer);
  945.   regs.si := ofs(requestbuffer);
  946.   regs.es := seg(replybuffer);
  947.   regs.di := ofs(replybuffer);
  948.   requestbuffer.len := 52;
  949.   replybuffer.len := 55;
  950.   requestbuffer.name_len := length(userid);
  951.   for i := 1 to length(userid) do requestbuffer.name[i] := userid[i];
  952.   requestbuffer.conntype[2] := $1;
  953.   requestbuffer.conntype[1] := $0;
  954.   replybuffer.conntype := 1;
  955.   msdos(regs);
  956.   retcode := regs.al;   {
  957.   if retcode = $96 then writeln('Server out of memory');
  958.   if retcode = $EF then writeln('Invalid name');
  959.   if retcode = $F0 then writeln('Wildcard not allowed');
  960.   if retcode = $FC then writeln('No such object *',userid,'*');
  961.   if retcode = $FE then writeln('Server bindery locked');
  962.   if retcode = $FF then writeln('Bindery failure'); }
  963.   hex_id := '';
  964.   if retcode = 0 then
  965.   begin
  966.    hex_id := hexdigits[replybuffer.uniqueid1[1] shr 4];
  967.    hex_id := hex_id + hexdigits[replybuffer.uniqueid1[1] and $0F];
  968.    hex_id := hex_id + hexdigits[replybuffer.uniqueid1[2] shr 4];
  969.    hex_id := hex_id + hexdigits[replybuffer.uniqueid1[2] and $0F];
  970.    hex_id := hex_id + hexdigits[replybuffer.uniqueid2[1] shr 4];
  971.    hex_id := hex_id + hexdigits[replybuffer.uniqueid2[1] and $0F];
  972.    hex_id := hex_id + hexdigits[replybuffer.uniqueid2[2] shr 4];
  973.    hex_id := hex_id + hexdigits[replybuffer.uniqueid2[2] and $0F];
  974.    { Now we chop off leading zeros }
  975.    while hex_id[1] = '0' do hex_id := copy(hex_id,2,length(hex_id));
  976.   end;
  977.    hexid := hex_id;
  978. end;
  979.  
  980.  
  981. Procedure GetConnectionInfo
  982. (Var LogicalStationNo: Integer; Var Name: String; Var HEX_ID: String;
  983.  Var ConnType : Integer; Var DateTime : String; Var retcode:integer);
  984.  
  985. Var
  986.   I,X            : Integer;
  987.   RequestBuffer  : Record
  988.                      PacketLength : Integer;
  989.                      FunctionVal  : Byte;
  990.                      ConnectionNo : Byte;
  991.                    End;
  992.   ReplyBuffer    : Record
  993.                      ReturnLength : Integer;
  994.                      UniqueID1    : Packed Array [1..2] of byte;
  995.                      UniqueID2    : Packed Array [1..2] of byte;
  996.                      ConnType     : Packed Array [1..2] of byte;
  997.                      ObjectName   : Packed Array [1..48] of Byte;
  998.                      LoginTime    : Packed Array [1..8] of Byte;
  999.                    End;
  1000.   Month          : String[3];
  1001.   Year,
  1002.   Day,
  1003.   Hour,
  1004.   Minute         : String[2];
  1005.  
  1006. Begin
  1007.   With RequestBuffer Do Begin
  1008.     PacketLength := 2;
  1009.     FunctionVal := 22;  { 22 = Get Station Info }
  1010.     ConnectionNo := LogicalStationNo;
  1011.   End;
  1012.   ReplyBuffer.ReturnLength := 62;
  1013.   With Regs Do Begin
  1014.     Ah := $e3;
  1015.     ds := 0;
  1016.     es := 0;
  1017.     Ds := Seg(RequestBuffer);
  1018.     Si := Ofs(RequestBuffer);
  1019.     Es := Seg(ReplyBuffer);
  1020.     Di := Ofs(ReplyBuffer);
  1021.   End;
  1022.   MsDos(Regs);
  1023.   name := '';
  1024.   hex_id := '';
  1025.   conntype := 0;
  1026.   datetime := '';
  1027.   If Regs.al = 0 Then Begin
  1028.     With ReplyBuffer Do Begin
  1029.       I := 1;
  1030.       While (I <= 48)  and (ObjectName[I] <> 0) Do Begin
  1031.         Name[I] := Chr(Objectname[I]);
  1032.         I := I + 1;
  1033.       End { while };
  1034.       Name[0] := Chr(I - 1);
  1035.       if name<>'' then
  1036.       begin
  1037.        Str(LoginTime[1]:2,Year);
  1038.        Month := Months[LoginTime[2]];
  1039.        Str(LoginTime[3]:2,Day);
  1040.        Str(LoginTime[4]:2,Hour);
  1041.        Str(LoginTime[5]:2,Minute);
  1042.        If Day[1] = ' ' Then Day[1] := '0';
  1043.        If Hour[1] = ' ' Then Hour[1] := '0';
  1044.        If Minute[1] = ' ' Then Minute[1] := '0';
  1045.        DateTime := Day+'-'+Month+'-'+Year+' ' + Hour + ':' + Minute;
  1046.       End;
  1047.     End { with };
  1048.   End;
  1049.   retcode := regs.al;
  1050.   if name<>'' then
  1051.   begin
  1052.    hex_id := '';
  1053.    hex_id := hexdigits[replybuffer.uniqueid1[1] shr 4];
  1054.    hex_id := hex_id + hexdigits[replybuffer.uniqueid1[1] and $0F];
  1055.    hex_id := hex_id + hexdigits[replybuffer.uniqueid1[2] shr 4];
  1056.    hex_id := hex_id + hexdigits[replybuffer.uniqueid1[2] and $0F];
  1057.    hex_id := hex_id + hexdigits[replybuffer.uniqueid2[1] shr 4];
  1058.    hex_id := hex_id + hexdigits[replybuffer.uniqueid2[1] and $0F];
  1059.    hex_id := hex_id + hexdigits[replybuffer.uniqueid2[2] shr 4];
  1060.    hex_id := hex_id + hexdigits[replybuffer.uniqueid2[2] and $0F];
  1061.    ConnType := replybuffer.conntype[2];
  1062.   { Now we chop off leading zeros
  1063.    while hex_id[1]='0' and do hex_id := copy(hex_id,2,length(hex_id));
  1064.    }
  1065.  End;
  1066. End { GetConnectInfo };
  1067.  
  1068. procedure login_to_file_server(obj_type:integer;_name,_password : string;var retcode:integer);
  1069. var   request_buffer : record
  1070.             B_length : integer;
  1071.          subfunction : byte;
  1072.               o_type : packed array [1..2] of byte;
  1073.          name_length : byte;
  1074.             obj_name : packed array [1..47] of byte;
  1075.      password_length : byte;
  1076.             password : packed array [1..27] of byte;
  1077.                  end;
  1078.  
  1079.         reply_buffer : record
  1080.             R_length : integer;
  1081.                  end;
  1082.  
  1083.                count : integer;
  1084.  
  1085. begin
  1086. With request_buffer do
  1087. begin
  1088.  B_length := 79;
  1089.  subfunction := $14;
  1090.  o_type[1] := 0;
  1091.  o_type[2] := obj_type;
  1092.  for count := 1 to 47 do obj_name[count] := $0;
  1093.  for count := 1 to 27 do password[count] := $0;
  1094.  if length(_name) > 0 then
  1095.     for count := 1 to length(_name) do obj_name[count]:=ord(upcase(_name[count]));
  1096.  if length(_password) > 0 then
  1097.     for count := 1 to length(_password) do password[count]:=ord(upcase(_password[count]));
  1098.  {set to full length of field}
  1099.  name_length := 47;
  1100.  password_length := 27;
  1101. end;
  1102. With reply_buffer do
  1103. begin
  1104.  R_length := 0;
  1105. end;
  1106.   With Regs Do Begin
  1107.     Ah := $e3;
  1108.     Ds := Seg(Request_Buffer);
  1109.     Si := Ofs(Request_Buffer);
  1110.     Es := Seg(reply_buffer);
  1111.     Di := Ofs(reply_buffer);
  1112.   End;
  1113.   MsDos(Regs);
  1114.   retcode := regs.al
  1115. end;
  1116.  
  1117. procedure logout;
  1118. {logout from all file servers}
  1119. begin
  1120.  regs.ah := $D7;
  1121.  msdos(regs);
  1122. end;
  1123.  
  1124. procedure logout_from_file_server(var id: integer);
  1125. {logout from one file server}
  1126. begin
  1127.  regs.ah := $F1;
  1128.  regs.al := $02;
  1129.  regs.dl := id;
  1130.  msdos(regs);
  1131. end;
  1132.  
  1133.  
  1134.  
  1135.  
  1136. procedure send_message_to_username(username,message : string; var retcode: integer);
  1137. VAR
  1138.    count1     : byte;
  1139.    userid     : string;
  1140.    stationid  : integer;
  1141.    ret_code   : integer;
  1142.  
  1143. begin
  1144.    ret_code := 1;
  1145.    for count1:= 1 to length(username) do
  1146.        username[count1]:=upcase(username[count1]); { Convert to upper case }
  1147.    getserverinfo;
  1148.    for count1:= 1 to serverinfo.connections_max do
  1149.    begin
  1150.      stationid := count1;
  1151.      getuser( stationid, userid, retcode);
  1152.       if userid = username then
  1153.         begin
  1154.         ret_code := 0;
  1155.         send_message_to_station(stationid, message, retcode);
  1156.       end;
  1157.      end; { end of count }
  1158.      retcode := ret_code;
  1159.      { retcode = 0 if sent,  1 if userid not found }
  1160. end; { end of procedure }
  1161.  
  1162.  
  1163. Procedure GetServerInfo;
  1164. Var
  1165.   RequestBuffer  : Record
  1166.                      PacketLength : Integer;
  1167.                      FunctionVal  : Byte;
  1168.                    End;
  1169.   I              : Integer;
  1170.  
  1171. Begin
  1172.   With RequestBuffer Do Begin
  1173.     PacketLength := 1;
  1174.     FunctionVal := 17;  { 17 = Get Server Info }
  1175.   End;
  1176.   ServerInfo.ReturnLength := 128;
  1177.   With Regs Do Begin
  1178.     Ah := $e3;
  1179.     Ds := Seg(RequestBuffer);
  1180.     Si := Ofs(RequestBuffer);
  1181.     Es := Seg(ServerInfo);
  1182.     Di := Ofs(ServerInfo);
  1183.   End;
  1184.   MsDos(Regs);
  1185.   With serverinfo do
  1186.   begin
  1187.    connections_max := connectionmax[1]*256 + connectionmax[2];
  1188.    connections_in_use := connectionuse[1]*256 + connectionuse[2];
  1189.    max_connected_volumes := maxconvol[1]*256 + maxconvol[2];
  1190.    peak_connections_used := peak_used[1]*256 + peak_used[2];
  1191.    name := '';
  1192.    i := 1;
  1193.    while ((server[i] <> 0) and (i<>48)) do
  1194.     begin
  1195.     name := name + chr(server[i]);
  1196.     i := i + 1;
  1197.     end;
  1198.    end;
  1199. End;
  1200.  
  1201. procedure GetServerName(var servername : string; var retcode : integer);
  1202. {-----------------------------------------------------------------}
  1203. { This routine returns the same as GetServerInfo.  This routine   }
  1204. { was kept to maintain compatibility with the older  novell unit. }
  1205. {-----------------------------------------------------------------}
  1206. begin
  1207.   getserverinfo;
  1208.   servername := serverinfo.name;
  1209.   retcode := 0;
  1210.   end;
  1211.  
  1212. procedure send_message_to_station(station:integer; message : string; var retcode: integer);
  1213. VAR
  1214.    req_buffer : record
  1215.    buffer_len : integer;
  1216.    subfunction: byte;
  1217.       c_count : byte;
  1218.        c_list : byte;
  1219.    msg_length : byte;
  1220.           msg : packed array [1..55] of byte;
  1221.           end;
  1222.  
  1223.    rep_buffer : record
  1224.    buffer_len : integer;
  1225.       c_count : byte;
  1226.        r_list : byte;
  1227.           end;
  1228.  
  1229.    count1     : integer;
  1230.  
  1231. begin
  1232.         if length(message) > 55 then message:=copy(message,1,55);
  1233.         With Regs do
  1234.         begin
  1235.          ah := $E1;
  1236.          ds:=seg(req_buffer);
  1237.          si:=ofs(req_buffer);
  1238.          es:=seg(rep_buffer);
  1239.          di:=ofs(rep_buffer);
  1240.         End;
  1241.         With req_buffer do
  1242.         begin
  1243.          buffer_len := 59;
  1244.          subfunction := 00;
  1245.          c_count := 1;
  1246.          c_list := station;
  1247.          for count1:= 1 to 55 do msg[count1]:= $00; { zero the buffer }
  1248.          msg_length := length(message); { message length }
  1249.          for count1:= 1 to length(message) do msg[count1]:=ord(message[count1]);
  1250.         End;
  1251.         With rep_buffer do
  1252.         begin
  1253.          buffer_len := 2;
  1254.          c_count := 1;
  1255.          r_list := 0;
  1256.         End;
  1257.         msdos( Regs );
  1258.         retcode:= rep_buffer.r_list;
  1259.    end;
  1260.  
  1261.  
  1262. procedure getuser( var _station: integer; var  _username: string; var retcode: integer);
  1263. {This procedure provides a shorter method of obtaining just the USERID.}
  1264. var
  1265.      gu_hexid : string;
  1266.   gu_conntype : integer;
  1267.   gu_datetime : string;
  1268.  
  1269. begin
  1270.   getconnectioninfo(_station,_username,gu_hexid,gu_conntype,gu_datetime,retcode);
  1271. end;
  1272.  
  1273.  
  1274. PROCEDURE GetNode( var hex_addr: string; var retcode: integer );
  1275. { get the physical station address }
  1276.  
  1277. Const
  1278.    Hex_Set  :packed array[0..15] of char = '0123456789ABCDEF';
  1279.  
  1280. Begin { GetNode }
  1281.    {Get the physical address from the Network Card}
  1282.    Regs.Ah := $EE;
  1283.    regs.ds := 0;
  1284.    regs.es := 0;
  1285.    MsDos(Regs);
  1286.    hex_addr := '';
  1287.    hex_addr := hex_addr + hex_set[(regs.ch shr 4)];
  1288.    hex_addr := hex_addr + hex_set[(regs.ch and $0f)];
  1289.    hex_addr := hex_addr + hex_set[(regs.cl shr 4) ];
  1290.    hex_addr := hex_addr + hex_set[(regs.cl and $0f)];
  1291.    hex_addr := hex_addr + hex_set[(regs.bh shr 4)];
  1292.    hex_addr := hex_addr + hex_set[(regs.bh and $0f)];
  1293.    hex_addr := hex_addr + hex_set[(regs.bl shr 4)];
  1294.    hex_addr := hex_addr + hex_set[(regs.bl and $0f)];
  1295.    hex_addr := hex_addr + hex_set[(regs.ah shr 4)];
  1296.    hex_addr := hex_addr + hex_set[(regs.ah and $0f)];
  1297.    hex_addr := hex_addr + hex_set[(regs.al shr 4)];
  1298.    hex_addr := hex_addr + hex_set[(regs.al and $0f)];
  1299.    retcode := 0;
  1300. End; { Getnode }
  1301.  
  1302.  
  1303. PROCEDURE Get_Internet_Address(station : integer; var net_number, node_addr, socket_number : string; var retcode : integer);
  1304.  
  1305. Const
  1306.    Hex_Set  :packed array[0..15] of char = '0123456789ABCDEF';
  1307.  
  1308. Var   Request_buffer : record
  1309.               length : integer;
  1310.          subfunction : byte;
  1311.           connection : byte;
  1312.                  end;
  1313.  
  1314.     Reply_Buffer : record
  1315.           length : integer;
  1316.          network : array [1..4] of byte;
  1317.             node : array [1..6] of byte;
  1318.           socket : array [1..2] of byte;
  1319.              end;
  1320.  
  1321.            count : integer;
  1322.       _node_addr : string;
  1323.   _socket_number : string;
  1324.      _net_number : string;
  1325.  
  1326. begin
  1327.  With Regs do
  1328.  begin
  1329.   ah := $E3;
  1330.   ds:=seg(request_buffer);
  1331.   si:=ofs(request_buffer);
  1332.   es:=seg(reply_buffer);
  1333.   di:=ofs(reply_buffer);
  1334.  End;
  1335.  With request_buffer do
  1336.  begin
  1337.   length := 2;
  1338.   subfunction := $13;
  1339.   connection := station;
  1340.  end;
  1341.  With reply_buffer do
  1342.  begin
  1343.   length := 12;
  1344.   for count := 1 to 4 do network[count] := 0;
  1345.   for count := 1 to 6 do node[count] := 0;
  1346.   for count := 1 to 2 do socket[count] := 0;
  1347.  end;
  1348.  msdos(regs);
  1349.  retcode := regs.al;
  1350.  _net_number := '';
  1351.  _node_addr := '';
  1352.  _socket_number := '';
  1353.  if retcode = 0 then
  1354.  begin
  1355.  for count := 1 to 4 do
  1356.      begin
  1357.      _net_number := _net_number + hex_set[ (reply_buffer.network[count] shr 4) ];
  1358.      _net_number := _net_number + hex_set[ (reply_buffer.network[count] and $0F) ];
  1359.      end;
  1360.  for count := 1 to 6 do
  1361.      begin
  1362.      _node_addr := _node_addr + (hex_set[ (reply_buffer.node[count] shr 4) ]);
  1363.      _node_addr := _node_addr + (hex_set[ (reply_buffer.node[count] and $0F) ]);
  1364.      end;
  1365.  for count := 1 to 2 do
  1366.      begin
  1367.      _socket_number := _socket_number + (hex_set[ (reply_buffer.socket[count] shr 4) ]);
  1368.      _socket_number := _socket_number + (hex_set[ (reply_buffer.socket[count] and $0F) ]);
  1369.      end;
  1370.  end; {end of retcode=0}
  1371.  net_number := _net_number;
  1372.  node_addr := _node_addr;
  1373.  socket_number := _socket_number;
  1374.  end;
  1375.  
  1376. procedure get_realname(var userid,realname:string; var retcode:integer);
  1377. var
  1378.     requestbuffer : record
  1379.     buffer_length : array [1..2] of byte;
  1380.       subfunction : byte;
  1381.       object_type : array [1..2] of byte;
  1382.     object_length : byte;
  1383.       object_name : array [1..47] of byte;
  1384.           segment : byte;
  1385.   property_length : byte;
  1386.     property_name : array [1..14] of byte;
  1387.     end;
  1388.  
  1389.       replybuffer : record
  1390.     buffer_length : array [1..2] of byte;
  1391.    property_value : array [1..128] of byte;
  1392.     more_segments : byte;
  1393.    property_flags : byte;
  1394.    end;
  1395.  
  1396.    count    : integer;
  1397.    id       : string;
  1398.    fullname : string;
  1399.  
  1400. begin
  1401.   id := 'IDENTIFICATION';
  1402.   With requestbuffer do begin
  1403.      buffer_length[2] := 0;
  1404.      buffer_length[1] := 69;
  1405.      subfunction  := $3d;
  1406.      object_type[1]:= 0;
  1407.      object_type[2]:= 01;
  1408.      segment := 1;
  1409.      object_length := 47;
  1410.      property_length := length(id);
  1411.      for count := 1 to 47 do object_name[count] := $0;
  1412.      for count := 1 to length(userid) do object_name[count] := ord(userid[count]);
  1413.      for count := 1 to 14 do property_name[count] := $0;
  1414.      for count := 1 to length(id) do property_name[count] := ord(id[count]);
  1415.      end;
  1416.   With replybuffer do begin
  1417.      buffer_length[1] := 130;
  1418.      buffer_length[2] := 0;
  1419.      for count := 1 to 128 do property_value[count] := $0;
  1420.      more_segments := 1;
  1421.      property_flags := 0;
  1422.      end;
  1423.   With Regs do begin
  1424.      Ah := $e3;
  1425.      Ds := Seg(requestbuffer);
  1426.      Si := Ofs(requestbuffer);
  1427.      Es := Seg(replybuffer);
  1428.      Di := Ofs(replybuffer);
  1429.      end;
  1430.   MSDOS(Regs);
  1431.   retcode := Regs.al;
  1432.   fullname := '';
  1433.   count := 1;
  1434.   repeat
  1435.    begin
  1436.    if replybuffer.property_value[count]<>0
  1437.       then fullname := fullname + chr(replybuffer.property_value[count]);
  1438.    count := count + 1;
  1439.    end;
  1440.    until ((count=128) or (replybuffer.property_value[count]=0));
  1441.   {if regs.al = $96 then writeln('server out of memory');
  1442.   if regs.al = $ec then writeln('no such segment');
  1443.   if regs.al = $f0 then writeln('wilcard not allowed');
  1444.   if regs.al = $f1 then writeln('invalid bindery security');
  1445.   if regs.al = $f9 then writeln('no property read priv');
  1446.   if regs.al = $fb then writeln('no such property');
  1447.   if regs.al = $fc then writeln('no such object');}
  1448.   if retcode=0 then realname := fullname else realname:='';
  1449. end;
  1450.  
  1451. procedure get_broadcast_mode(var bmode:integer);
  1452. begin
  1453.  regs.ah := $de;
  1454.  regs.dl := $04;
  1455.  msdos(regs);
  1456.  bmode := regs.al;
  1457. end;
  1458.  
  1459. procedure set_broadcast_mode(bmode:integer);
  1460. begin
  1461.  if ((bmode > 3) or (bmode < 0)) then bmode := 0;
  1462.  regs.ah := $de;
  1463.  regs.dl := bmode;
  1464.  msdos(regs);
  1465.  bmode := regs.al;
  1466. end;
  1467.  
  1468. procedure get_broadcast_message(var bmessage: string; var retcode : integer);
  1469. var requestbuffer : record
  1470.      bufferlength : array [1..2] of byte;
  1471.       subfunction : byte;
  1472.       end;
  1473.  
  1474.       replybuffer : record
  1475.      bufferlength : array [1..2] of byte;
  1476.     messagelength : byte;
  1477.           message : array [1..58] of byte;
  1478.           end;
  1479.     count : integer;
  1480.  
  1481. begin
  1482.   With Requestbuffer do begin
  1483.      bufferlength[1] := 1;
  1484.      bufferlength[2] := 0;
  1485.      subfunction := 1;
  1486.      end;
  1487.   With replybuffer do begin
  1488.      bufferlength[1] := 59;
  1489.      bufferlength[2] := 0;
  1490.      messagelength := 0;
  1491.      end;
  1492.      for count := 1 to 58 do replybuffer.message[count] := $0;
  1493.  
  1494.   With Regs do begin
  1495.      Ah := $e1;
  1496.      Ds := Seg(requestbuffer);
  1497.      Si := Ofs(requestbuffer);
  1498.      Es := Seg(replybuffer);
  1499.      Di := Ofs(replybuffer);
  1500.      end;
  1501.   MSDOS(Regs);
  1502.   retcode := Regs.al;
  1503.   bmessage := '';
  1504.   count := 0;
  1505.   if replybuffer.messagelength > 58 then replybuffer.messagelength := 58;
  1506.   if replybuffer.messagelength > 0 then
  1507.      for count := 1 to replybuffer.messagelength do
  1508.      bmessage := bmessage + chr(replybuffer.message[count]);
  1509.   { retcode = 0 if no message,  1 if message was retreived }
  1510.   if length(bmessage) = 0 then retcode := 1 else retcode := 0;
  1511.   end;
  1512.  
  1513. procedure get_server_datetime(var _year,_month,_day,_hour,_min,_sec,_dow:integer);
  1514. var replybuffer : record
  1515.            year : byte;
  1516.           month : byte;
  1517.             day : byte;
  1518.            hour : byte;
  1519.          minute : byte;
  1520.          second : byte;
  1521.             dow : byte;
  1522.             end;
  1523.  
  1524. begin
  1525.   With Regs do begin
  1526.      Ah := $e7;
  1527.      Ds := Seg(replybuffer);
  1528.      Dx := Ofs(replybuffer);
  1529.      end;
  1530.   MSDOS(Regs);
  1531.   retcode := Regs.al;
  1532.   _year := replybuffer.year;
  1533.   _month := replybuffer.month;
  1534.   _day := replybuffer.day;
  1535.   _hour := replybuffer.hour;
  1536.   _min := replybuffer.minute;
  1537.   _sec := replybuffer.second;
  1538.   _dow := replybuffer.dow;
  1539. end;
  1540.  
  1541. procedure set_date_from_server;
  1542. var replybuffer : record
  1543.            year : byte;
  1544.           month : byte;
  1545.             day : byte;
  1546.            hour : byte;
  1547.          minute : byte;
  1548.          second : byte;
  1549.             dow : byte;
  1550.             end;
  1551.  
  1552. begin
  1553.   With Regs do begin
  1554.      Ah := $e7;
  1555.      Ds := Seg(replybuffer);
  1556.      Dx := Ofs(replybuffer);
  1557.      end;
  1558.   MSDOS(Regs);
  1559.   setdate(replybuffer.year+1900,replybuffer.month,replybuffer.day);
  1560. end;
  1561.  
  1562. procedure set_time_from_server;
  1563. var replybuffer : record
  1564.            year : byte;
  1565.           month : byte;
  1566.             day : byte;
  1567.            hour : byte;
  1568.          minute : byte;
  1569.          second : byte;
  1570.             dow : byte;
  1571.             end;
  1572.  
  1573. begin
  1574.   With Regs do begin
  1575.      Ah := $e7;
  1576.      Ds := Seg(replybuffer);
  1577.      Dx := Ofs(replybuffer);
  1578.      end;
  1579.   MSDOS(Regs);
  1580.   settime(replybuffer.hour,replybuffer.minute,replybuffer.second,0);
  1581. end;
  1582.  
  1583. procedure get_server_version(var _version : string);
  1584. var  count,x : integer;
  1585.  
  1586.        request_buffer : record
  1587.         buffer_length : integer;
  1588.           subfunction : byte;
  1589.           end;
  1590.  
  1591.          reply_buffer : record
  1592.         buffer_length : integer;
  1593.                 stuff : array [1..512] of byte;
  1594.                 end;
  1595.  
  1596.         strings : array [1..3] of string;
  1597. begin
  1598.   With Regs do begin
  1599.      Ah := $e3;
  1600.      Ds := Seg(request_buffer);
  1601.      Si := Ofs(request_buffer);
  1602.      Es := Seg(reply_buffer);
  1603.      Di := Ofs(reply_buffer);
  1604.      end;
  1605.   With request_buffer do
  1606.   begin
  1607.      buffer_length := 1;
  1608.      subfunction := $c9;
  1609.   end;
  1610.   With reply_buffer do
  1611.   begin
  1612.      buffer_length := 512;
  1613.      for count := 1 to 512 do stuff[count] := $00;
  1614.   end;
  1615.   MSDOS(Regs);
  1616.   for count := 1 to 3 do strings[count] := '';
  1617.   x := 1;
  1618.   With reply_buffer do
  1619.   begin
  1620.     for count := 1 to 256 do
  1621.     begin
  1622.      if stuff[count] <> $0 then
  1623.         begin
  1624.          if not ((stuff[count]=32) and (strings[x]='')) then strings[x] := strings[x] + chr(stuff[count]);
  1625.         end;
  1626.      if stuff[count] = $0 then if x <> 3 then x := x + 1;
  1627.     end;
  1628.   End; { end of with }
  1629.   _version := strings[2];
  1630. end;
  1631.  
  1632. procedure open_message_pipe(var _connection, retcode : integer);
  1633. var  request_buffer : record
  1634.       buffer_length : integer;
  1635.         subfunction : byte;
  1636.    connection_count : byte;
  1637.     connection_list : byte;
  1638.                 end;
  1639.  
  1640.       reply_buffer : record
  1641.      buffer_length : integer;
  1642.   connection_count : byte;
  1643.        result_list : byte;
  1644.                end;
  1645. begin
  1646.   With Regs do begin
  1647.      Ah := $e1;
  1648.      Ds := Seg(request_buffer);
  1649.      Si := Ofs(request_buffer);
  1650.      Es := Seg(reply_buffer);
  1651.      Di := Ofs(reply_buffer);
  1652.      end;
  1653.   With request_buffer do
  1654.   begin
  1655.      buffer_length := 3;
  1656.      subfunction := $06;
  1657.      connection_count := $01;
  1658.      connection_list := _connection;
  1659.   end;
  1660.   With reply_buffer do
  1661.   begin
  1662.      buffer_length := 2;
  1663.      connection_count := 0;
  1664.      result_list := 0;
  1665.   end;
  1666.   MSDOS(Regs);
  1667.   retcode := reply_buffer.result_list;
  1668. end;
  1669.  
  1670. procedure close_message_pipe(var _connection, retcode : integer);
  1671. var  request_buffer : record
  1672.       buffer_length : integer;
  1673.         subfunction : byte;
  1674.    connection_count : byte;
  1675.     connection_list : byte;
  1676.                 end;
  1677.  
  1678.       reply_buffer : record
  1679.      buffer_length : integer;
  1680.   connection_count : byte;
  1681.        result_list : byte;
  1682.                end;
  1683. begin
  1684.   With Regs do begin
  1685.      Ah := $e1;
  1686.      Ds := Seg(request_buffer);
  1687.      Si := Ofs(request_buffer);
  1688.      Es := Seg(reply_buffer);
  1689.      Di := Ofs(reply_buffer);
  1690.      end;
  1691.   With request_buffer do
  1692.   begin
  1693.      buffer_length := 3;
  1694.      subfunction := $07;
  1695.      connection_count := $01;
  1696.      connection_list := _connection;
  1697.   end;
  1698.   With reply_buffer do
  1699.   begin
  1700.      buffer_length := 2;
  1701.      connection_count := 0;
  1702.      result_list := 0;
  1703.   end;
  1704.   MSDOS(Regs);
  1705.   retcode := reply_buffer.result_list;
  1706. end;
  1707.  
  1708. procedure check_message_pipe(var _connection, retcode : integer);
  1709. var request_buffer : record
  1710.      buffer_length : integer;
  1711.        subfunction : byte;
  1712.   connection_count : byte;
  1713.    connection_list : byte;
  1714.                end;
  1715.  
  1716.       reply_buffer : record
  1717.      buffer_length : integer;
  1718.   connection_count : byte;
  1719.        result_list : byte;
  1720.                end;
  1721. begin
  1722.   With Regs do begin
  1723.      Ah := $e1;
  1724.      Ds := Seg(request_buffer);
  1725.      Si := Ofs(request_buffer);
  1726.      Es := Seg(reply_buffer);
  1727.      Di := Ofs(reply_buffer);
  1728.      end;
  1729.   With request_buffer do
  1730.   begin
  1731.      buffer_length := 3;
  1732.      subfunction := $08;
  1733.      connection_count := $01;
  1734.      connection_list := _connection;
  1735.   end;
  1736.   With reply_buffer do
  1737.   begin
  1738.      buffer_length := 2;
  1739.      connection_count := 0;
  1740.      result_list := 0;
  1741.   end;
  1742.   MSDOS(Regs);
  1743.   retcode := reply_buffer.result_list;
  1744. end;
  1745.  
  1746.  
  1747. procedure send_personal_message(var _connection : integer; var _message : string; var retcode : integer);
  1748. var count : integer;
  1749.  
  1750.       request_buffer : record
  1751.        buffer_length : integer;
  1752.          subfunction : byte;
  1753.     connection_count : byte;
  1754.      connection_list : byte;
  1755.       message_length : byte;
  1756.              message : array [1..126] of byte;
  1757.                  end;
  1758.  
  1759.         reply_buffer : record
  1760.        buffer_length : integer;
  1761.     connection_count : byte;
  1762.          result_list : byte;
  1763.                  end;
  1764.  
  1765. begin
  1766.   With Regs do begin
  1767.      Ah := $e1;
  1768.      Ds := Seg(request_buffer);
  1769.      Si := Ofs(request_buffer);
  1770.      Es := Seg(reply_buffer);
  1771.      Di := Ofs(reply_buffer);
  1772.      end;
  1773.   With request_buffer do
  1774.   begin
  1775.      subfunction := $04;
  1776.      connection_count := $01;
  1777.      connection_list := _connection;
  1778.      message_length := length(_message);
  1779.      buffer_length := length(_message) + 4;
  1780.      for count := 1 to 126 do message[count] := $00;
  1781.      if message_length > 0 then for count := 1 to message_length do
  1782.         message[count] := ord(_message[count]);
  1783.   end;
  1784.   With reply_buffer do
  1785.   begin
  1786.      buffer_length := 2;
  1787.      connection_count := 0;
  1788.      result_list := 0;
  1789.   end;
  1790.   MSDOS(Regs);
  1791.   retcode := reply_buffer.result_list;
  1792. end;
  1793.  
  1794.  
  1795. procedure get_personal_message(var _connection : integer; var _message : string; var retcode : integer);
  1796. var count : integer;
  1797.  
  1798.       request_buffer : record
  1799.        buffer_length : integer;
  1800.          subfunction : byte;
  1801.                  end;
  1802.  
  1803.         reply_buffer : record
  1804.        buffer_length : integer;
  1805.    source_connection : byte;
  1806.       message_length : byte;
  1807.       message_buffer : array [1..126] of byte;
  1808.                  end;
  1809.  
  1810. begin
  1811.     With Regs do begin
  1812.      Ah := $e1;
  1813.      Ds := Seg(request_buffer);
  1814.      Si := Ofs(request_buffer);
  1815.      Es := Seg(reply_buffer);
  1816.      Di := Ofs(reply_buffer);
  1817.      end;
  1818.   With request_buffer do
  1819.   begin
  1820.      buffer_length := 1;
  1821.      subfunction := $05;
  1822.   end;
  1823.   With reply_buffer do
  1824.   begin
  1825.      buffer_length := 128;
  1826.      source_connection := 0;
  1827.      message_length := 0;
  1828.      for count := 1 to 126 do message_buffer[count] := $0;
  1829.   end;
  1830.   MSDOS(Regs);
  1831.   _connection := reply_buffer.source_connection;
  1832.   _message := '';
  1833.   retcode := reply_buffer.message_length;
  1834.   if retcode > 0 then for count := 1 to retcode do
  1835.      _message := _message + chr(reply_buffer.message_buffer[count]);
  1836. end;
  1837.  
  1838. procedure log_file(lock_directive:integer; log_filename: string; log_timeout:integer; var retcode:integer);
  1839. begin
  1840.     With Regs do begin
  1841.      Ah := $eb;
  1842.      Ds := Seg(log_filename);
  1843.      Dx := Ofs(log_filename);
  1844.      BP := log_timeout;
  1845.      end;
  1846. msdos(regs);
  1847. retcode := regs.al;
  1848. end;
  1849.  
  1850. procedure release_file(log_filename: string; var retcode:integer);
  1851. begin
  1852.     With Regs do begin
  1853.      Ah := $ec;
  1854.      Ds := Seg(log_filename);
  1855.      Dx := Ofs(log_filename);
  1856.      end;
  1857. msdos(regs);
  1858. retcode := regs.al;
  1859. end;
  1860.  
  1861. procedure clear_file(log_filename: string; var retcode:integer);
  1862. begin
  1863.     With Regs do begin
  1864.      Ah := $ed;
  1865.      Ds := Seg(log_filename);
  1866.      Dx := Ofs(log_filename);
  1867.      end;
  1868. msdos(regs);
  1869. retcode := regs.al;
  1870. end;
  1871.  
  1872. procedure clear_file_set;
  1873. begin
  1874.  regs.Ah := $cf;
  1875.  msdos(regs);
  1876.  retcode := regs.al;
  1877. end;
  1878.  
  1879. procedure lock_file_set(lock_timeout:integer; var retcode:integer);
  1880. begin
  1881.  regs.ah := $CB;
  1882.  regs.bp := lock_timeout;
  1883.  msdos(regs);
  1884.  retcode := regs.al;
  1885. end;
  1886.  
  1887. procedure release_file_set;
  1888. begin
  1889.  regs.ah := $CD;
  1890.  msdos(regs);
  1891. end;
  1892.  
  1893. procedure open_semaphore( _name:string;
  1894.                           _initial_value:shortint;
  1895.                           var _open_count:integer;
  1896.                           var _handle:longint;
  1897.                           var retcode:integer);
  1898. var s_name : array [1..129] of byte;
  1899.     count : integer;
  1900.     semaphore_handle : array [1..2] of word;
  1901. begin
  1902.   if (_initial_value < 0) or (_initial_value > 127) then _initial_value := 0;
  1903.   for count := 1 to 129 do s_name[count] := $00; {zero buffer}
  1904.   if length(_name) > 127 then _name := copy(_name,1,127); {limit name length}
  1905.   if length(_name) > 0 then for count := 1 to length(_name) do s_name[count+1] := ord(_name[count]);
  1906.   s_name[1] := length(_name);
  1907.   regs.ah := $C5;
  1908.   regs.al := $00;
  1909.   move(_initial_value, regs.cl, 1);
  1910.   regs.ds := seg(s_name);
  1911.   regs.dx := ofs(s_name);
  1912.   msdos(regs);
  1913.   retcode := regs.al;
  1914.   _open_count := regs.bl;
  1915.   semaphore_handle[1]:=regs.cx;
  1916.   semaphore_handle[2]:=regs.dx;
  1917.   move(semaphore_handle,_handle,4);
  1918. end;
  1919.  
  1920. procedure close_semaphore(var _handle:longint; var retcode:integer);
  1921. var semaphore_handle : array [1..2] of word;
  1922. begin
  1923.  move(_handle,semaphore_handle,4);
  1924.  regs.ah := $C5;
  1925.  regs.al := $04;
  1926.  regs.cx := semaphore_handle[1];
  1927.  regs.dx := semaphore_handle[2];
  1928.  msdos(regs);
  1929.  retcode := regs.al;  { 00h=successful   FFh=Invalid handle}
  1930. end;
  1931.  
  1932. procedure examine_semaphore(var _handle:longint; var _value:shortint; var _count, retcode:integer);
  1933. var semaphore_handle : array [1..2] of word;
  1934. begin
  1935.     move(_handle,semaphore_handle,4);
  1936.     regs.ah := $C5;
  1937.     regs.al := $01;
  1938.     regs.cx := semaphore_handle[1];
  1939.     regs.dx := semaphore_handle[2];
  1940.     msdos(regs);
  1941.     retcode := regs.al; {00h=successful FFh=invalid handle}
  1942.     move(regs.cx, _value, 1);
  1943.     _count := regs.dl;
  1944. end;
  1945.  
  1946. procedure signal_semaphore(var _handle:longint; var retcode:integer);
  1947. var semaphore_handle : array [1..2] of word;
  1948. begin
  1949.     move(_handle,semaphore_handle,4);
  1950.     regs.ah := $C5;
  1951.     regs.al := $03;
  1952.     regs.cx := semaphore_handle[1];
  1953.     regs.dx := semaphore_handle[2];
  1954.     msdos(regs);
  1955.     retcode := regs.al;
  1956.     {00h=successful   01h=overflow value > 127   FFh=invalid handle}
  1957. end;
  1958.  
  1959. procedure wait_on_semaphore(var _handle:longint; _timeout:integer; var retcode:integer);
  1960. var semaphore_handle : array [1..2] of word;
  1961. begin
  1962.     move(_handle,semaphore_handle,4);
  1963.     regs.ah := $C5;
  1964.     regs.al := $02;
  1965.     regs.bp := _timeout; {units in 1/18 of second,   0 = no wait}
  1966.     regs.cx := semaphore_handle[1];
  1967.     regs.dx := semaphore_handle[2];
  1968.     msdos(regs);
  1969.     retcode := regs.al;
  1970.     {00h=successful   FEh=timeout failure   FFh=invalid handle}
  1971. end;
  1972.  
  1973. procedure clear_connection(connection_number : integer; var retcode : integer);
  1974. var con_num : byte;
  1975.  
  1976.     request_buffer : record
  1977.             length : integer;
  1978.        subfunction : byte;
  1979.            con_num : byte;
  1980.                end;
  1981.  
  1982.       reply_buffer : record
  1983.             length : integer;
  1984.                end;
  1985.  
  1986. begin
  1987.   with request_buffer do begin
  1988.      length := 4;
  1989.      con_num := connection_number;
  1990.      subfunction := $D2;
  1991.      end;
  1992.   reply_buffer.length := 0;
  1993.   with regs do begin
  1994.      Ah := $e3;
  1995.      Ds := Seg(request_buffer);
  1996.      Si := Ofs(request_buffer);
  1997.      Es := Seg(reply_buffer);
  1998.      Di := Ofs(reply_buffer);
  1999.      end;
  2000.   msdos(regs);
  2001.   retcode := regs.al;
  2002. end;
  2003.  
  2004.  
  2005. function getnamefromhexid(hexid : string) : string;
  2006. {
  2007. return a user name by inspecting bindery for corresponding hexid
  2008. rml may 1993
  2009. }
  2010. var
  2011.      r : integer;
  2012.      realname,hex_id                : string;
  2013.      lastseen              : longint;
  2014.      object_type           : integer;
  2015.      object_name           : string;
  2016.      replyid               : longint;
  2017.      replytype             : integer;
  2018.      replyname             : string;
  2019.      replyflag             : integer;
  2020.      replysecurity         : byte;
  2021.      replyproperties       : integer;
  2022.      reply_id : array[1..4] of byte absolute replyid;
  2023. begin
  2024.      lastseen := -1;      { -1 means start at first entry }
  2025.      object_type := 1;    {1=users 2=group 3=print server 4=file server}
  2026.      object_name := '*';  {wildcard '*' means everyone}
  2027.      r := 0;
  2028.      repeat
  2029.            scan_object(lastseen, object_type, object_name,
  2030.                  replyid, replytype, replyname, replyflag, replysecurity,
  2031.                  replyproperties, r);
  2032.            lastseen := replyid;
  2033.            hex_id := '';
  2034.            if r = 0 then
  2035.            begin
  2036.                hex_id := hexdigits[reply_id[1] shr 4];
  2037.                hex_id := hex_id + hexdigits[reply_id[1] and $0F];
  2038.                hex_id := hex_id + hexdigits[reply_id[2] shr 4];
  2039.                hex_id := hex_id + hexdigits[reply_id[2] and $0F];
  2040.                hex_id := hex_id + hexdigits[reply_id[3] shr 4];
  2041.                hex_id := hex_id + hexdigits[reply_id[3] and $0F];
  2042.                hex_id := hex_id + hexdigits[reply_id[4] shr 4];
  2043.                hex_id := hex_id + hexdigits[reply_id[4] and $0F];
  2044.            end;
  2045.      until (r <> 0) or (hex_id = hexid);
  2046.      if (r = 0) then
  2047.         getnamefromhexid := replyname
  2048.      else
  2049.          getnamefromhexid := '*';
  2050. end; { getnamefromhexid }
  2051.  
  2052.  
  2053. var
  2054.    s : string;
  2055. begin
  2056.      apiavailable := false;
  2057.      get_server_version(currentversion);
  2058.      if (currentversion > '') then
  2059.         apiavailable := true;
  2060. end. { end of unit novell }
  2061.  
  2062.